package main

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/tealeg/xlsx"
)

type TransInfo struct {
	Src string `json:"src"`
	Dst string `json:"dst"`
}

type TransResult struct {
	From        string      `json:"from"`
	To          string      `json:"to"`
	TransResult []TransInfo `json:"trans_result"`
}

var (
	targetPath *string
	appid      string
	sign       string
	language   *string
)

func main() {
	targetPath = flag.String("targetPath", ".", "-targetPath 待翻译目标文件夹")
	zone := flag.String("zone", "US", "-zone 指定地区编号")
	language = flag.String("language", "en", "-language 目标语言,en=英文、jp=日语")
	flag.Parse()

	fileName := *zone + ".xlsx"
	fmt.Println()
	fmt.Print("正在处理：" + fileName)

	xlFile, error := xlsx.OpenFile(fileName)
	if error != nil {
		fmt.Printf("%s", error)
	}

	// 遍历sheet页
	sheet := xlFile.Sheet["需要翻译的文字"]
	fmt.Print(" >> " + sheet.Name)
	fmt.Println()

	totalNum := len(sheet.Rows)
	fmt.Printf("本次待翻译语句数量: %d \n", totalNum)

	// 遍历row
	for lineNum, row := range sheet.Rows {
		//忽略标题行或者空行...
		if lineNum == 0 || len(row.Cells) == 0 {
			continue
		} else {
			str := row.Cells[0].String()
			var buffer bytes.Buffer

			r := []rune(str)
			cnstr := ""
			flag := false
			for i := 0; i < len(r); i++ {
				if r[i] <= 40869 && r[i] >= 19968 {
					// 是中文
					flag = true
					cnstr = cnstr + string(r[i])
				} else {
					//不是中文原样保留
					if flag && len(cnstr) > 0 {
						transResult, _ := Translate(cnstr)
						buffer.WriteString(transResult)
						cnstr = ""
						flag = false
					}

					buffer.WriteString(string(r[i]))
				}
			}

			//不是中文原样保留
			if flag && len(cnstr) > 0 {
				transResult, _ := Translate(cnstr)
				buffer.WriteString(transResult)
				cnstr = ""
				flag = false
			}

			fmt.Print("(")
			fmt.Print(lineNum)
			fmt.Print("/")
			fmt.Print(totalNum)
			fmt.Print(")")
			fmt.Print(str)
			fmt.Print("==>>")
			transResult := buffer.String()
			row.AddCell().SetString(transResult)
			fmt.Println(transResult)
		}

		if lineNum%60 == 0 {
			xlFile.Save("./" + fileName)
		}
	}

	// 写文件
	xlFile.Save("./" + fileName)
	fmt.Println("翻译完成：" + fileName)
}

// 翻译方法
func Translate(target string) (string, error) {
	time.Sleep(1 * time.Second)
	// 字段名 类型 必填参数 描述 备注
	// q TEXT Y 请求翻译query UTF-8编码
	// from TEXT Y 翻译源语言 语言列表(可设置为auto)
	// to TEXT Y 译文语言 语言列表(不可设置为auto)
	// appid TEXT Y APP ID 可在管理控制台查看
	// salt TEXT Y 随机数
	// sign TEXT Y 签名 appid+q+salt+密钥 的MD5值

	params := make(map[string]string)
	// 读取接口调用参数
	appid = os.Getenv("appid")
	sign = os.Getenv("sign")
	// 构建翻译接口
	url := "http://api.fanyi.baidu.com/api/trans/vip/translate"

	params["q"] = target
	params["from"] = "zh"
	params["to"] = *language
	params["appid"] = appid
	params["salt"] = strconv.Itoa(rand.Int())
	s := params["appid"] + params["q"] + params["salt"] + sign
	params["sign"] = GetStringMd5(s)

	var strBuf string
	for k, v := range params {
		strBuf = strBuf + k + "=" + v + "&"
	}
	paramsStr := strings.TrimRight(strBuf, "&")

	result, err := SendHttpPost(url, paramsStr)
	return result, err
}

// 获得MD5加密串
func GetStringMd5(s string) string {
	md5 := md5.New()
	md5.Write([]byte(s))
	md5Str := hex.EncodeToString(md5.Sum(nil))
	return md5Str
}

// 发送post请求，返回翻译结果
func SendHttpPost(url string, paramsStr string) (string, error) {
	resp, err := http.Post(url, "application/x-www-form-urlencoded", strings.NewReader(paramsStr))
	if err != nil {
		return "", err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	// 解析json结果
	jsonStr := string(body)
	var result TransResult
	json.Unmarshal([]byte(jsonStr), &result)
	var s string
	if len(result.TransResult) > 0 {
		s = result.TransResult[0].Dst
	}
	return s, nil
}
